
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Microsoft.SharePoint;

namespace PS.WebParts.Rollup
{
    static class Util
    {
        public static Dictionary<string, string> GuessTypes(DataTable table)
        {
           int columnCount = table.Columns.Count;

            List<string> bools = new List<string>(columnCount);
            List<string> numbers = new List<string>(columnCount);
            List<string> datetimes = new List<string>(columnCount);

            List<string> master = new List<string>(columnCount);

            foreach (DataColumn dc in table.Columns)
            {
                bools.Add(dc.ColumnName);
                numbers.Add(dc.ColumnName);
                datetimes.Add(dc.ColumnName);
                master.Add(dc.ColumnName);
            }


            foreach (DataRow dr in table.Rows)
            {
            
                foreach(string columnName in master)
                {
                    object oVal = dr[columnName];
                    if (oVal == null) continue;
                    
                    string strVal = oVal.ToString();

                    if (strVal.Trim().Length == 0) continue;

                    if(bools.Contains(columnName))
                    {
                       bool tb;
                       if (!bool.TryParse(strVal, out tb))
                           bools.Remove(columnName);  
                      
                     }

                     if (numbers.Contains(columnName))
                     {
                         decimal tn;
                         if (!decimal.TryParse(strVal, out tn))
                             numbers.Remove(columnName);
                     }

                     if (datetimes.Contains(columnName))
                     {
                         DateTime td;
                         if (!DateTime.TryParse(strVal, out td))
                             datetimes.Remove(columnName);
                     }

                }

                if (bools.Count < 1 && numbers.Count < 1 && datetimes.Count < 1)
                    break;

            }

            Dictionary<string, string> types = new Dictionary<string, string>(bools.Count + numbers.Count + datetimes.Count);

            foreach (string columnName in numbers)
            {
                types.Add(columnName, "numbers");
               

            }
            foreach (string columnName in datetimes)
            {
                if (!types.ContainsKey(columnName))
                    types.Add(columnName, "datetime");

            }
            foreach (string columnName in bools)
            {
                if (!types.ContainsKey(columnName))
                    types.Add(columnName, "boolean");
            }

            return types;
        }

        public static Type GuessType(DataTable table, string columnName)
        {
            bool isNum = true;
            bool isDate = true;
            foreach (DataRow row in table.Rows)
            {
                object val = row[columnName];
                if (val == null) continue;

                string str = val.ToString();
                if (str.Trim().Length == 0)
                    continue;

                if (isNum)
                {
                    decimal dVal;
                    if (!decimal.TryParse(str, out dVal))
                    {
                        isNum = false;
                    }
                }

                if (isDate)
                {
                    DateTime dVal;
                    if (!DateTime.TryParse(str, out dVal))
                    {
                        isDate = false;
                    }
                }

                if (!isNum && !isDate)
                    return typeof (string);
            }

            if (isNum)
                return typeof (Decimal);
            else
                return typeof(DateTime);
        }

        public static DataTable CreateTypedTable(DataTable dt, string propertyName)
        {
            if (dt == null || propertyName == null) return null;
            
            DataTable typedTable = new DataTable(dt.TableName);

            foreach (DataColumn dc in dt.Columns)
            {
                DataColumn newColumn = typedTable.Columns.Add();
                CopyColumnProperties(dc, ref newColumn);

                if(dc.ExtendedProperties != null 
                    && dc.ExtendedProperties.ContainsKey(propertyName))
                {
                    try
                    {
                        SPFieldType fieldType = (SPFieldType)dc.ExtendedProperties[propertyName];
                        Type t = FieldToType(fieldType);
                        if (t != null)
                            newColumn.DataType = t;
                    }
                    catch(InvalidCastException)
                    {}
                }
            }
            CopyTable(dt, ref typedTable);
            return typedTable;                       
        }

        public static Type FieldToType(SPFieldType fieldType)
        {
            switch (fieldType)
            {
                case SPFieldType.Integer:
                    return typeof (int);

                case SPFieldType.Number:
                    //return typeof (int);

                case SPFieldType.Currency:
                    return typeof (decimal);

                case SPFieldType.DateTime:
                    return typeof (DateTime);
                
                case SPFieldType.Boolean:
                    return typeof (bool);

                case SPFieldType.Guid:
                    return typeof (Guid);


                case SPFieldType.Note:
                case SPFieldType.Text:
                    return typeof (string);

                default:
                    return null;
            }
        }

        public static void CopyTable(DataTable source, ref DataTable target)
        {
            foreach (DataRow r in source.Rows)
            {
                DataRow newRow = target.NewRow();
                for(int i = 0; i<r.ItemArray.Length; ++i)
                {
                    newRow[i] = r[i];
                }
                target.Rows.Add(newRow);
            }
        }

        public static void CopyColumnProperties(DataColumn source, ref DataColumn target)
        {
            target.AllowDBNull = source.AllowDBNull;
            target.AutoIncrement = source.AutoIncrement;
            target.AutoIncrementSeed =source.AutoIncrementSeed;
            target.AutoIncrementStep = source.AutoIncrementStep;
            target.Caption = source.Caption;
            target.ColumnMapping = source.ColumnMapping;
            target.ColumnName = source.ColumnName;
            target.DataType = source.DataType;
            target.DateTimeMode = source.DateTimeMode;
            target.Expression = source.Expression;
            target.Namespace = source.Namespace;
            target.Prefix = source.Prefix;
            target.ReadOnly = source.ReadOnly;
            target.Unique = source.Unique;

            if (source.ExtendedProperties != null)
            {
                foreach (DictionaryEntry entry in source.ExtendedProperties)
                {
                    target.ExtendedProperties.Add(entry.Key, entry.Value);
                }
            }
        }


/*
        private  static void TryConvert(DataTable table, string columnName)
        {
            bool notNum = false;
            bool notDate = false;

            string dateColumn = columnName + "DATE";
            string numColumn = columnName + "NUM";

            table.Columns.Add(numColumn, typeof(decimal));
            table.Columns.Add(dateColumn, typeof(DateTime));
            

            for(int i = 0; i < table.Columns.Count; i++)//DataRow dr in table.Rows)
            {
                DataRow dr = table.Rows[i];


                if(!notNum)
                {
                    Decimal dec;

                    if (decimal.TryParse(dr[columnName].ToString(), out dec))
                        dr[numColumn] = dec;
                    else
                        notNum = true;

                }

                if (!notDate)
                {
                    DateTime dt;

                    if (DateTime.TryParse(dr[columnName].ToString(), out dt))
                        dr[dateColumn] = dt;
                    else
                        notDate = true;


                }

                if (notDate && notNum)
                    break;

            }
            
            if(notDate && notNum)
            {
                table.Columns.Remove(dateColumn);
                table.Columns.Remove(numColumn);


            }
            else
            {
                table.Columns.Remove(columnName);

                if(!notDate)
                {
                    table.Columns[dateColumn].ColumnName = columnName;

 table.Columns.Remove(numColumn);

                }
                else
                {
                     table.Columns[numColumn].ColumnName = columnName;

 table.Columns.Remove(dateColumn);



                }


            }

            
                
            }
*/



        


        public static string ScopeUp(string currentSeverRelUrl, string relPath)
        {
            string [] s = currentSeverRelUrl.Replace(@"\", "/").TrimEnd('/').Split('/');
            string [] s2 = relPath.Replace(@"\", "/").TrimEnd('/').Split('/');

            if (!relPath.StartsWith("../"))
                throw new ArgumentException("Relative path must begin with ../", "relPath");
            
            int clip = s2[0] == "" ? 1 : 0;
            while( clip < s2.Length && s2[clip] == ".." )
            {
                clip++;
            }
            
            StringBuilder sb = new StringBuilder(currentSeverRelUrl.Length + relPath.Length);
            int i = s.Length - clip;
            for (int a = 0; a < i; a++ )
            {
                sb.Append(s[a]);
                sb.Append("/");
            }

            for (int a = clip; a < s2.Length; a++)
            {
                sb.Append(s2[a]);
                sb.Append("/");
            }

            string res = sb.ToString();
            return res != "" ? res.TrimEnd('/') : "/";
        }

        public static string ScopeDown(string currentRelUrl, string relPath)
        {
            string ret;
            if (!relPath.StartsWith("./"))
            {
                ret = relPath;
            }
            else
            {
                if (relPath.Length == 2)
                    ret = "";
                else
                    ret = relPath.Substring(2);
            }

            string res = currentRelUrl.TrimEnd('/') + "/" + ret;
            return res.TrimEnd('/');
        }

        public static string ResolveRelUrl(string serverRelUrl, string url)
        {
            string effectiveRelUrl;
            if (url.StartsWith("./") || !url.StartsWith("/"))
                effectiveRelUrl = ScopeDown(serverRelUrl, url);
            else
            {
                if (url.StartsWith("../"))
                {
                    effectiveRelUrl = ScopeUp(serverRelUrl, url);
                }
                else
                    effectiveRelUrl = url;
            }
            return effectiveRelUrl;
        }
    }
}
